/*
 * Copyright (c) 2009. Silenus Consultoria, S.L.U.
 */
package es.silenus.detecta.client;

import org.apache.commons.configuration.Configuration;

import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;

import java.io.IOException;

import java.net.MalformedURLException;
import java.net.URL;


/**
 * Abstract form authenticator.
 *
 * @author <a href="mailto:malonso@silenus-consultoria.es">Mariano Alonso</a>
 *
 * @since 12-ago-2009 10:08:56
 */
public abstract class AbstractFormAuthenticator {
	/**
	 * The configuration.
	 */
	protected Configuration configuration;

	/**
	 * The client.
	 */
	protected HttpClient client;

/**
   * Constructor.
   */
	public AbstractFormAuthenticator() {
	}

	/**
	 * Sets the configuration.
	 *
	 * @param configuration the configuration.
	 */
	public void setConfiguration(final Configuration configuration) {
		this.configuration = configuration;
	}

	/**
	 * Sets the client.
	 *
	 * @param client the client.
	 */
	public void setClient(final HttpClient client) {
		this.client = client;
	}

	/**
	 * Performs the user login.
	 *
	 * @throws IOException if an I/O error occurs.
	 */
	public abstract void login() throws IOException;

	/**
	 * Performs the user logout.
	 *
	 * @throws IOException if an I/O error occurs.
	 */
	public abstract void logout() throws IOException;

	/**
	 * Retrieves an absolute URL based on the given URI.
	 *
	 * @param URI the URI.
	 *
	 * @return an absolute URL based on the given URI.
	 *
	 * @throws MalformedURLException if URI is not correct.
	 */
	public String getURL(final String URI) throws MalformedURLException {
		URL url = new URL(String.format("%s%s", configuration.getString("host.url"), URI));

		return url.toExternalForm();
	}

	/**
	 * Retrieves a secure absolute URL based on the given URI.
	 *
	 * @param URI the URI.
	 *
	 * @return a secure absolute URL based on the given URI.
	 *
	 * @throws MalformedURLException if URI is not correct.
	 */
	public String getSecureURL(final String URI) throws MalformedURLException {
		URL url = new URL(String.format("%s%s", configuration.getString("secure.host.url"), URI));

		return url.toExternalForm();
	}

	/**
	 * Retrieves the user name.
	 *
	 * @return the user name.
	 */
	public String getUserName() {
		return configuration.getString("user.name");
	}

	/**
	 * Retrieves the user password.
	 *
	 * @return the user password.
	 */
	public String getUserPassword() {
		return configuration.getString("user.password");
	}

	/**
	 * Retrieves the response value.
	 *
	 * @param response the response.
	 * @param startToken a start token.
	 * @param endToken an end token.
	 *
	 * @return the response value or null when not found.
	 */
	protected String getResponseValue(final String response, final String startToken, final String endToken) {
		int index = response.indexOf(startToken);

		if(index > 0) {
			int end = response.indexOf(endToken, index + startToken.length() + 1);

			return response.substring(index + startToken.length(), end);
		}

		return null;
	}

	/**
	 * Formats the method response.
	 *
	 * @param method the method.
	 *
	 * @return the formatted response.
	 *
	 * @throws IOException if response could not be read.
	 */
	public String formatMethodResponse(HttpMethod method) throws IOException {
		return String.format(
			"[%d - %s]\n%s", method.getStatusCode(), method.getStatusText(), method.getResponseBodyAsString());
	}

	/**
	 * Print the cookies into a string.
	 *
	 * @return the cookies into a string.
	 */
	protected String printCookies() {
		StringBuilder builder = new StringBuilder();
		Cookie[] cookies = client.getState().getCookies();

		for(Cookie cookie : cookies) {
			builder.append(
				String.format(
					"[Domain=%s, Path=%s] %s=%s", cookie.getDomain(), cookie.getPath(), cookie.getName(), cookie.getValue()));
			builder.append(",");
		}

		return builder.toString();
	}

	/**
	 * Retrieves a named cookie value.
	 *
	 * @param name the cookie name.
	 *
	 * @return the cookie value.
	 */
	protected String getCookie(final String name) {
		Cookie[] cookies = client.getState().getCookies();

		for(Cookie cookie : cookies) {
			if(name.equals(cookie.getName())) {
				return cookie.getValue();
			}
		}

		return null;
	}
}
